#include "stm32f10x.h"

void RCC_Config(void);
void USART1_Config(void);
void USART1_SendChar(unsigned char);
void USART1_SendString(unsigned char *);
void USART1_Send4Bytes(unsigned long);
void EXTI_PA8_Config(void);
void GPIO_LED_Config(void);

void IR_GET(void);
void IR_Timing_Reload(void);
void IR_Timing_Stop(void);
unsigned char Conversion_TimingNum2BIN(unsigned int);

unsigned int TimingNum;
unsigned char IR_Timing_Flag;
unsigned int IR_TimingNum_Tmp;
unsigned int IR_KeyCode;
unsigned int IR_CheckKeyCode;

int main(void)
{
	RCC_Config();
	USART1_Config();
	USART1_SendString("USART1 was ready!!!\r\n");
	EXTI_PA8_Config();
	GPIO_LED_Config();
	while(1)
	{
		if(IR_Timing_Flag == 0x1 && TimingNum >= 0x3600)
		{
			IR_Timing_Stop();
		}
		if(IR_Timing_Flag == 0x22)
		{
			IR_Timing_Stop();
			if((IR_KeyCode & 0xFF) != (~IR_CheckKeyCode & 0xFF))
			{
				IR_KeyCode = 0x0;
				IR_CheckKeyCode = 0x0;
			}
			USART1_Send4Bytes(IR_KeyCode);
			USART1_SendString("\r\n");
			if(IR_KeyCode == 0x0C)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_0)));
			}
			else if(IR_KeyCode == 0x18)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_1)));
			}
			else if(IR_KeyCode == 0x5E)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_2, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2)));
			}
			else if(IR_KeyCode == 0x08)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_3, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_3)));
			}
			else if(IR_KeyCode == 0x1C)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_4)));
			}
			else if(IR_KeyCode == 0x5A)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5)));
			}
			else if(IR_KeyCode == 0x42)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_6, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_6)));
			}
			else if(IR_KeyCode == 0x52)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_7)));
			}
			else if(IR_KeyCode == 0x4A)
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_11, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_11)));
			}
			else
			{
				GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_2, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_3, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_6, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)0x1);
				GPIO_WriteBit(GPIOA, GPIO_Pin_11, (BitAction)0x1);
			}
		}
	}
}

void RCC_Config(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
}

void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART1, &USART_InitStructure);

	USART_Cmd(USART1, ENABLE);
}

void USART1_SendChar(unsigned char a)
{
	USART_SendData(USART1, (unsigned char)a);
	while (!(USART1->SR & USART_FLAG_TXE));
}

void USART1_SendString(unsigned char * p)
{
	while(* p)
	{
		USART1_SendChar(* p++);
	}
}

void USART1_Send4Bytes(unsigned long a)
{
	USART1_SendString("0x");
	int i = 28;
	unsigned char b;
	while(i >= 0)
	{
		b = (unsigned char)((a >> i) & 0x0000000F);
		if(b < 0xA)
		{
			b += 0x30;
		}
		else
		{
			b += 0x37;
		}
		USART1_SendChar(b);
		i -= 4;
	}
}

void EXTI_PA8_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line8;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;

	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_Init(&NVIC_InitStructure);
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	EXTI_Init(&EXTI_InitStructure);
}

void GPIO_LED_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_2, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_3, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_6, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)0x1);
	GPIO_WriteBit(GPIOA, GPIO_Pin_11, (BitAction)0x1);
}

void IR_GET(void)
{
	if(IR_Timing_Flag != 0x0)
	{
		IR_TimingNum_Tmp = TimingNum;
		IR_Timing_Reload();
		if(IR_Timing_Flag >= 0x2 && IR_Timing_Flag <= 0x11)
		{
			if(IR_TimingNum_Tmp > 0x0 || IR_TimingNum_Tmp < 0x9C4)
			{
				IR_Timing_Flag++;
			}
			else
			{
				IR_Timing_Stop();
			}
		}
		else if(IR_Timing_Flag >= 0x12 && IR_Timing_Flag <= 0x19)
		{
			if(IR_TimingNum_Tmp > 0x0 || IR_TimingNum_Tmp < 0x9C4)
			{
				IR_KeyCode |= Conversion_TimingNum2BIN(IR_TimingNum_Tmp) << (IR_Timing_Flag - 0x12);
				IR_Timing_Flag++;
			}
			else
			{
				IR_Timing_Stop();
			}
		}
		else if(IR_Timing_Flag >= 0x1A && IR_Timing_Flag <= 0x21)
		{
			if(IR_TimingNum_Tmp > 0x0 || IR_TimingNum_Tmp < 0x9C4)
			{
				IR_CheckKeyCode |= Conversion_TimingNum2BIN(IR_TimingNum_Tmp) << (IR_Timing_Flag - 0x1A);
				IR_Timing_Flag++;
			}
			else
			{
				IR_Timing_Stop();
			}
		}
		else if(IR_Timing_Flag == 0x1)
		{
			if(IR_TimingNum_Tmp >= 0x3326 && IR_TimingNum_Tmp <= 0x3552)
			{
				IR_Timing_Flag++;
			}
			else
			{
				IR_Timing_Stop();
			}
		}
		else
		{
			IR_Timing_Stop();
		}
	}
	else
	{
		IR_Timing_Reload();
		IR_KeyCode = 0x0;
		IR_CheckKeyCode = 0x0;
		IR_Timing_Flag = 0x1;
	}
}

void IR_Timing_Reload(void)
{
	SysTick->CTRL = 0x0;
	SysTick->LOAD = 0x0;
	SysTick->VAL = 0x0;
	TimingNum = 0x0;
	SysTick_Config(SystemCoreClock / 1000000);
}

void IR_Timing_Stop(void)
{
	IR_Timing_Flag = 0x0;
	SysTick->CTRL = 0x0;
}

unsigned char Conversion_TimingNum2BIN(unsigned int a)
{
	if(a < 0x600)
	{
		return 0;
	}
	else
	{
		return 1;
	}
}